/*
 * MockLowLevelDispatcher.java    0.0.1    19/set/2009
 * 
 * Copyright (c) 2009 mentalsmash.org
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * The use of the Apache License does not indicate that this project is
 * affiliated with the Apache Software Foundation.
 */ 
package org.mentalsmash.tazio.net.cs.server.impl;
/*
 * TODO: This class is here instead of the mock package because of the visibility of some methods
 *      of HandlerAdapter. When someone has time, it would be good to move this class in the 
 *      appropriate place
 */

import java.io.IOException;
import java.nio.channels.SelectableChannel;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;

import org.mentalsmash.tazio.net.cs.server.ProtocolHandler;
import org.mentalsmash.tazio.net.cs.server.impl.BufferPool;
import org.mentalsmash.tazio.net.cs.server.impl.ChannelFacade;
import org.mentalsmash.tazio.net.cs.server.impl.HandlerAdapter;
import org.mentalsmash.tazio.net.cs.server.impl.LowLevelDispatcher;

/**
 * A mock implementation of the LowLevelDispatcher to use in tests
 * @version    0.0.1    19/set/2009    
 * @author     Andrea Reale <andrea.reale@gmail.com>
 */
public class MockLowLevelDispatcher extends LowLevelDispatcher {

	
	
	private volatile boolean running = false;
	
	//SYNCHORNIZED SET
	private final Set<HandlerAdapter> registrations;
	
	//In this implementation the queue grows indefinitely without being cleared. That's not a problem
	//since it's used just in tests
	private final BlockingQueue<HandlerAdapter> waitingForModsMock = new ArrayBlockingQueue<HandlerAdapter>(100);
	private final BufferPool pool;
	
	
	/**
	 * Create a new Mock implementation of the LowLevelDispatcher for use in tests
	 * @param e an executor. It won't be used by this implementation.
	 * @param pool a buffer pool, better if it works
	 * @throws IOException
	 */
	public MockLowLevelDispatcher(Executor e, BufferPool pool)
			throws IOException {
		super(e, pool);
		this.pool=pool;
		registrations = Collections.synchronizedSet(new HashSet<HandlerAdapter>());
		
	}
	
	/**
	 * In this mock implementation checks whether a boolean variable indicating
	 * the running status is set to true. This implementation cannot actually be run by 
	 * a real thread :)
	 */
	public boolean isRunning() {
		return running;
	}

	/**
	 * Sets the boolean <code>running</code> internal variable to true
	 * @return null
	 */
	@Override
	public Thread start(){
		running = true;
		return null;
	}
	
	/*
	 * -- Runnalble interface implementation --
	 */
	
	/**
	 * NO-OP
	 */
	@Override
	public void run() {
		//NO-OP
	}
	
	/*
	 * -- Dispatcher interface implementation --
	 */

	
	/**
	 * NO-OP
	 */
	@Override
	public void dispatch() throws IOException {
		//NO-OP
	}





	/**
	 * Sets the <code>running</code> instance variable to false
	 */
	public void stop() {
		running = false;
	}
	

	@Override
	/**
	 * Fake registration: creats an handler adapter and adds it to a registrations set
	 */
	public ChannelFacade register(SelectableChannel chan, ProtocolHandler handler)
			throws IOException {
		HandlerAdapter adapter = new HandlerAdapter(handler, this, this.pool);
		registrations.add(adapter);
		return adapter;
	}
	

	/**
	 * Fake unregistration: removes the handler adapter (passed as a ChannelFacade) from the  
	 * registration set
	 */
	@Override
	public void unregister(ChannelFacade chan) {
		HandlerAdapter adapter = (HandlerAdapter)chan;
		registrations.remove(adapter);
	}
	
	/**
	 * True if the adapter is in the registrations set
	 * @param toTest
	 * @return True if the adapter is in the registrations set
	 */
	public boolean isHandlerRegistered(HandlerAdapter toTest){
		return registrations.contains(toTest);
	}
	
	@Override
	public void enqueueStatusChange(HandlerAdapter adapter) {
		waitingForModsMock.add(adapter);
	}
	
	public boolean isQueuedForModifications(HandlerAdapter adapter){
		return waitingForModsMock.contains(adapter);
	}



}
